#include"bootpack.h"
#include <string.h>

 CQUEUE intbuf; //中断数据
 CQUEUE consolecq ;
 BOOTINFO *btinfo ;
 MEMORY_MANAGEMENT * memman =(MEMORY_MANAGEMENT *) MEMORY_MANAGE_ADDR ;
 
 SHEET_MANAGEMENT * shtman ;
 SHEET * sht_back , *sht_mouse ,* sht_console ;//,*sht_window ;
 
TASK *task_bootpack ,*task_console ,*task_c;

struct KEYBOARD_STATE  { 
	int key_leds ;     //当前指向窗体 ，shift按键，键盘灯 (4 scrollLOCK  ,5  NUMBERLOCK , 6 CAPSLOCK) ,我们对他进行了>>4的操作 ，所以变为123位
	int key_shift ; 
} keyboard_state;

CMD cmd1 ; 

struct FILEINFO *finfo =  (struct FILEINFO *) (ADR_DISKIMG + 0x002600) ;  //文件系统

int * fat12 ;// 2880个扇区的fat表
   

extern TIMER_MANAGEMENT timer_man ;
 //TIMER timer ; 

extern char keytable0[0x80] ;
extern char keytable1[0x80] ;

void task_console_main () ;





/*这个是main函数*/
void HariMain(void)
{   
	MOUSE_INFO mouseinfo;
	mouseinfo.phase = 0 ;
//	int mx =150,my = 90 ; 
	unsigned int memsize = 0 ,freememsize =0;
	/*320 * 200   x: 0-319  , y: 0-199*/
	int mx =150,my =90 ,m ,a; 
	//extern char hankaku[4096]; //导入ascii字体
	btinfo = ( BOOTINFO*) ADR_BOOTINFO ; //在asmhead.nas中定义的
	//键盘状态
	keyboard_state.key_leds =(btinfo->leds >> 4) & 7 ;   
	keyboard_state.key_shift =0 ;
	
	char s[50] ; //sprintf函数的字符缓冲区
	INTDATA buf ; //临时变量

	TIMER *t1 ,*t2,*t3 ;
	int task_console_esp,task_c_esp ;// 堆栈指针
	int i ,j ;

	unsigned char * buf_sht_back ,buf_sht_mouse[256] ,*buf_sht_console;//*buf_sht_window ; //图层内容缓存

	init_gdtidt(); //初始化gdt、idt
	init_pic(); //初始化PIC


	
	
	//InitQueue(&mousebuf) ; //初始化鼠标数据buffer队列

//取消4个中断的PIC禁用
	io_sti(); //开启中断
	io_out8(PIC0_IMR,0xf8); //11111000  int20 ,int21,irq2
	io_out8(PIC1_IMR,0xef); //   int2c

	init_keyboard(); 
	enable_mouse();
//timer 初始化
	init_pit() ;
//	timer_man_setbuf(&intbuf);

//内存管理初始化
	memman_init (memman);
	memman->totalsize =  memtest(0x100000 ,0xffffffff) ;
	memsize = memman->totalsize >>20 ;
	freememsize = memman_free_total (memman)  ;
//文件系统 ：
	 fat12 = memman_alloc_4k (memman,4*2880) ;
	file_fatdecode (fat12 ,ADR_DISKIMG + 0x00200) ; //读fat表,并解压到int *fat字段中


// timer管理： 
	t1 = timer_alloc() ;
	t2 = timer_alloc() ;
	t3 = timer_alloc() ;
	 timer_init( t1,&intbuf, 1 );
	 timer_init( t2,&intbuf, 2 );
	 timer_init( t3,&intbuf, 3 );
	 timer_settime (t1, 1000) ;
	 timer_settime (t3, 10000) ;
	 timer_settime (t2, 1000);

//	图层管理
	init_palette();
	shtman = shtman_init (memman ,btinfo->vram ,btinfo->scrnx ,btinfo->scrny) ;

	*( (int *)0x0fe4) = (int *)shtman ;
	sht_mouse = sheet_alloc (shtman) ;
	sht_back =sheet_alloc (shtman) ;
//	sht_window = sheet_alloc (shtman) ;
	sht_console = sheet_alloc (shtman) ;

//	buf_sht_window   = (unsigned char *) memman_alloc_4k(memman, 160 * 52);
	buf_sht_console   = (unsigned char *) memman_alloc_4k(memman, 512 * 320);
	buf_sht_back =(unsigned char *) memman_alloc_4k(memman ,btinfo->scrnx * btinfo->scrny);
	sheet_setbuf (sht_back,buf_sht_back,btinfo->scrnx,btinfo->scrny,-1) ; //无透明色
	sheet_setbuf (sht_mouse,buf_sht_mouse,16,16,99) ;//透明色99
//	sheet_setbuf (sht_window,buf_sht_window,160,52,-1) ;
	sheet_setbuf (sht_console,buf_sht_console,512,320,-1) ;

	init_screen(buf_sht_back ,btinfo->scrnx ,btinfo->scrny); //初始化屏幕
	init_mouse_cursor8(buf_sht_mouse,99); //初始化鼠标
	make_window8(buf_sht_console, 512, 320, " Console" ,1) ;
	make_textbox8(sht_console, 8, 28, 512-16,320-37, COL8_000000);
//	make_window8(buf_sht_window, 160, 52, "window" ,0) ;
//	make_textbox8(sht_window, 8, 28, 144, 16, COL8_FFFFFF);


	sheet_slide (sht_back,0,0) ;
	sheet_slide (sht_mouse,mx,my);
//	sheet_slide (sht_window,80,80);
	sheet_slide (sht_console,80,80);
	sheet_updown (sht_back,0) ;// 设置高度
//	sheet_updown (sht_window,1);
	sheet_updown (sht_console,2);
	sheet_updown (sht_mouse,99) ;//设置高度


	
	//sprintf(s,"error code : %d",a);
	//putchars8_sht ( sht_back ,0 ,32,COL8_FFFFFF ,COL8_000000 , s,40); 
	
/*
	for (i = 0 ; i < 128 ;i ++) { 
		for (j = 0 ; j < 128 ;j++) { 
			sht_back->buf[j + i *btinfo->scrnx] = rgb2pal (j ,i ,0 ,j,i);
		}
	}
*/
// 命令行初始化 : 
	cmd_init (&cmd1);
	cmd1.sheet = sht_console ;
//加载背景图片 :
	a = readIMG (sht_back);
//多任务切换:

	 //初始化: 
	 task_bootpack =task_init (memman) ; //bootpack代码段任务的初始化
	 InitQueue(&intbuf,task_bootpack) ; //初始化中断数据buffer队列
	 task_bootpack->cq = &intbuf ; 
	 task_console = task_alloc () ;
	 InitQueue(&consolecq,task_console) ;
	 task_console->cq = &consolecq ;

	 task_c = task_alloc () ; 
	 //*(int *)0x0fec = (int ) sht_back ;
	//task_console->tss.ldtr = 0 ;
	task_console->tss.iomap = 0x40000000 ;
	 
	task_console_esp = memman_alloc_4k(memman,64 * 1024) +64 *1024 - 8 ; //本来是减4 ，但是后面把sht_back的地址放在esp上了 ，所以直接-8 
	task_console->tss.eip = (int) &task_console_main;
	task_console->tss.eflags = 0x00000202; /* IF = 1; */
	task_console->tss.eax = 0;
	task_console->tss.ecx = 0;
	task_console->tss.edx = 0;
	task_console->tss.ebx = 0;
	task_console->tss.esp = task_console_esp;
	task_console->tss.ebp = 0;
	task_console->tss.esi = 0;
	task_console->tss.edi = 0;
	task_console->tss.es = 1 * 8;
	task_console->tss.cs = 2 * 8;
	task_console->tss.ss = 1 * 8;
	task_console->tss.ds = 1 * 8;
	task_console->tss.fs = 1 * 8; 
	task_console->tss.gs = 1 * 8;
	*((int *) (task_console_esp + 4)) = (int) &cmd1;
	
//c 
	
	//task_c->tss.ldtr = 0 ;
	task_c->tss.iomap = 0x40000000 ; 
	task_c_esp = memman_alloc_4k(memman,64 * 1024) +64 *1024 - 8 ; //本来是减4 ，但是后面把sht_back的地址放在esp上了 ，所以直接-8 
	task_c->tss.eip = (int) &task_console_main;
	task_c->tss.eflags = 0x00000202; // IF = 1; 
	task_c->tss.eax = 0;
	task_c->tss.ecx = 0;
	task_c->tss.edx = 0;
	task_c->tss.ebx = 0;
	task_c->tss.esp = task_c_esp;
	task_c->tss.ebp = 0;
	task_c->tss.esi = 0;
	task_c->tss.edi = 0;
	task_c->tss.es = 1 * 8;
	task_c->tss.cs = 2 * 8;
	task_c->tss.ss = 1 * 8;
	task_c->tss.ds = 1 * 8;
	task_c->tss.fs = 1 * 8; 
	task_c->tss.gs = 1 * 8;
//	*((int *) (task_c_esp + 4)) = (int) sht_window;
	

	task_run  (task_bootpack,1,0); //bootpack.c
	task_run  (task_console,2,0);
//	task_run  (task_c,2,0);
	

	


	for (;;){ 
		io_cli();
		/**
		sprintf(s,"%010d",timer_man.count);
		putchars8_sht ( sht_console ,35 ,28  ,COL8_000000 ,COL8_C6C6C6 , s,10); 
		*/

		//boxfill8 (buf_sht_window,160,COL8_C6C6C6,35,28,119,43) ;
		//putchars8(buf_sht_window,160,35,28,COL8_000000,s);
		//sheet_refresh_bysht (sht_window);

		if (EmptyQueue(&intbuf) ) {
			task_sleep (task_bootpack) ;
			io_sti() ;
		}else {  //表示有键盘输入或者鼠标输入
			DeQueue (&intbuf ,&buf);
			io_sti() ;
			switch (buf.code) { 
				case INTDATA_CODE_MOUSE:
					if (0!=mouse_decode (&mouseinfo,buf.data)) { //表示3个字节数据已经处理完，开始进行一次鼠标操作
						if (mouseinfo.btn ==0x01) {
							//按了左键
							sheet_slide(sht_console,mx,my);
						}
						if (mouseinfo.btn ==0x02) {
							//按了右键
						}
						if (mouseinfo.btn ==0x04) {
							//按了滚轮
						}
						//先用背景色填充原先的鼠标
						//boxfill8(btinfo->vram, btinfo->scrnx, COL8_840084, mx, my, mx + 15, my + 15);
						mx +=mouseinfo.x ;
						my +=mouseinfo.y ;
						if (mx <0) { 
							mx = 0 ;
						}
						if (my <0){ 
							my = 0 ;
						}
						if (mx >btinfo->scrnx -1){
							mx = btinfo->scrnx -1 ;
						}
						if (my > btinfo->scrny-1) { 
							my = btinfo->scrny-1 ;
						}
						//写出鼠标坐标数据x,y
					//	sprintf(s,"mouse ,data= %3d %3d", mx,my);
						//boxfill8(buf_sht_back, btinfo->scrnx, COL8_000000, 0, 16, 32 * 8 - 1, 31);
						//putchars8(buf_sht_back,btinfo->scrnx,0,16,COL8_FFFFFF,s);
						//sheet_refresh(shtman,0,16,32*8-1,31) ; //这句以后再删去

					//	putchars8_sht ( sht_back ,0 ,16,COL8_FFFFFF ,COL8_000000 , s,40); 


						//重绘鼠标
						sheet_slide(sht_mouse,mx,my);
						sheet_refresh_bysht(sht_mouse) ;
						
					}
					break ; 
				case INTDATA_CODE_KEYBOARD:  //键盘
					switch  (buf.data) { 
						case 0x2a : //左shift on 
							keyboard_state.key_shift |=  1 ; break ; 
						case 0x36 : //右shift on 
							keyboard_state.key_shift |=  2 ; break ;
						case 0xaa ://左shift off
							keyboard_state.key_shift &= ~1 ; break ; 
						case 0xb6 ://右shift off 
							keyboard_state.key_shift &= ~2 ; break ;
						case 0x3a ://CAPS LOCK 
							keyboard_state.key_leds ^= (1<<2) ;break ;  //把第3位取反  ,和^ 4效果相同
						case 0x3b :
							if (0x3b ==buf.data && keyboard_state.key_shift !=0 && task_console->tss.esp0 !=0 ) {  //shift +f1  ，且ss0不为0
								cmd_putchars(&cmd1,"\n Break(key) : \n");
								io_cli () ;
								task_console->tss.eax = (int) & (task_console->tss.esp0) ;
								task_console->tss.eip = (int) asm_end_app;
								io_sti () ;
							}


							break ;

						default : 
							EnQueue (task_console->cq ,buf); break ;	
					}

					
					
					if (buf.data >=0 && buf.data < 0x80) { 
						//sprintf(s,"keyboard ,data = %02x , ch =" ,buf.data);
						//m = strlen(s) ;
						s[m] = keytable0 [buf.data] ;
						s[m+1] = 0 ;
					}else { 
						//sprintf(s,"keyboard ,data = %02x" ,buf.data);
					}
					//putchars8_sht ( sht_back ,0 ,0,COL8_FFFFFF ,COL8_000000 , s,50); 
					break ;
				case INTDATA_CODE_TIMER : 
					if (buf.data ==1) { 
						//task_sleep (task_bootpack);
						//task_remove (task_bootpack) ;
					}
					//sprintf(s,"%010d",buf.data);
					//putchars8_sht ( sht_window ,35 ,28  ,COL8_000000 ,COL8_C6C6C6 , s,10); 
					 break ;
 			} 

		}

	}

}

void task_console_main ( CMD * cmd) { 
	
	
	//临时变量
	char s[40];  
	INTDATA dt ; 
	//光标闪烁定时器
	TIMER * timer; 
	FILE_HANDLER  fhandler0[8];
	int state ; 
	
	* ((int *)0x0fec) = cmd ; 

	TASK * task = task_now () ;	

	timer = timer_alloc () ;
	timer_init (timer ,task->cq,0);
	timer_settime (timer ,50);

	for (state = 0 ; state < 8 ; state ++) { 
		fhandler0[state].buf = 0 ; 
	}
	task->fhandler = fhandler0 ;
	task->fat = fat12 ;

	putchars8_sht ( cmd->sheet,8 ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , cmd->head,strlen(cmd->head));  //画str字符串
	for (;;){
		
		io_cli ();
		if (EmptyQueue(task->cq) ) {
			//task_sleep (task) ;
			io_sti() ;
		}else { 
			DeQueue (task->cq,&dt);
			io_sti ();
			if (dt.code ==INTDATA_CODE_TIMER) {
				
				if (dt.data == 0) { 
					timer_init (timer ,task->cq,1);
					cmd->cursor_color = COL8_FFFFFF ;
				}else { 
					timer_init (timer ,task->cq,0);
					cmd->cursor_color = COL8_000000 ;
				}
				timer_settime (timer ,50);
				boxfill8(cmd->sheet->buf ,cmd->sheet->bxsize,cmd->cursor_color,cmd->cursor_x ,cmd->cursor_y+12,cmd->cursor_x+7 ,cmd->cursor_y +12+3) ;
				sheet_refresh_bysht2 (cmd->sheet ,cmd->cursor_x ,cmd->cursor_y+12 ,cmd->cursor_x +7 ,cmd->cursor_y +12+3);
				//boxfill8(buf_sht_back, btinfo->scrnx, COL8_000000, 0, 32, 32 * 8 - 1, 47);
			}
			if (dt.code ==INTDATA_CODE_KEYBOARD) {
				switch (dt.data) { 

					case 0x0e : //退格
						if (cmd->length >0) { 
							cmd->cmdline[cmd->length-1] ='\0' ;
							cmd->length --;
							
							putchars8_sht ( cmd->sheet,cmd->cursor_x ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , " ",1); //清除闪烁的cursor  
							cmd->cursor_x -=8 ;
							if (cmd->cursor_x < 8) { 
								cmd->cursor_x = cmd->sheet->bxsize -24 ;
								cmd->cursor_y -=16 ;
							}
							putchars8_sht ( cmd->sheet,cmd->cursor_x ,cmd->cursor_y ,COL8_FFFFFF, COL8_000000 , " ",1);  //清除字符
						}
						 break ;
					case 0x0f : //Tab键
						 break ;
					case 0x1c : //回车键
						state = cmd_exec (cmd) ;
							
						 break ;
					default :
						if (dt.data <=0x80 && dt.data >=0) {	
							if (keyboard_state.key_shift ==0) {  //shift 没按住  
								s[0] = keytable0[dt.data];
							}else { 
								s[0] = keytable1[dt.data];
							}
							
							if ('A' <= s[0] && s[0] <='Z' ){  //判断是否需要切换大小写
								if ( (keyboard_state.key_leds &4)==0 && (keyboard_state.key_shift ==0)  ||  
								      (keyboard_state.key_leds)&4 !=0 && (keyboard_state.key_shift !=0 ) ) { 
									s[0] = s[0] +0x20 ;
								}
							}
								
							cmd_putcmdchar(cmd,s[0],1);
						}
						 break ;
				} 
			}
			
		}
		
	}
}



//

//以sp为分割符 分割字符串, 返回切出的总字符串个数
int str_split (char source[] ,char dest[][10]  ,char sp) { 
	int length = strlen (source);
	int flag = 0  ; //匹配到字符串
	int i=0,j=0,k=0;
	if (length <=0) {return 0;}

	for (i =0 ;i<length;i++) {
		if (source[i] ==sp) { 
			if (flag ==0){ //表示是命令之前的空格
				continue ;
			}else {  //表示是第一个命令串之后的空格
				dest[j][k] ='\0' ;
				k = 0 ;
				j++ ;
				flag = 0 ;
			}
		}
		else {
			flag =1 ;
			dest[j][k] = source[i];
			k++ ;
		}
	}
	if (source[length-1] !=sp) { 
		dest[j][k] ='\0' ;
		j++ ;
	}
	return j ;
}


/*查找字符是否存在,存在则返回下标,不存在则返回-1*/
int str_strchr (const char * str, char ch) { 
	int i = 0 ,ret =-1; 
	while (str[i] != '\0') { 
		if (str[i] ==ch) { 
			ret = i ; 
			break ;
		}else { 
			i ++ ;
		}
	}
	return ret ;
}


